#include"SLDST.h"

void SLDST::Execute(instruction* sldst_instr){
    std::cout << "SLDST Execute called. Opcode: " << sldst_instr->get_opcode() << std::endl;
    addr_size_t temp_addr = 0;
    switch (sldst_instr->get_opcode()) {
        case SLDH:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), HW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), HW);
            }
            this->do_SLDH(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SLDHU:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), HW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), HW);
            }
            this->do_SLDHU(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SLDW:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(),DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), DW);
            }
            this->do_SLDW(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SLDDW:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), DW);
            }
            std::cout << "Executing SLDDW instruction..." << std::endl;
            this->do_SLDDW(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            std::cout << "SLDDW execution completed." << std::endl;
            break;
        case SLDB:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), DB);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), DB);
            }
            this->do_SLDB(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SLDDB:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), DB);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), DB);
            }
            this->do_SLDDB(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SLDBU:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), B);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), B);
            }
            this->do_SLDBU(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SLDDBU:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), DB);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), DB);
            }
            this->do_SLDDBU(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SSTH:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), HW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), HW);
            }
            this->do_SSTH(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SSTW:
            std::cout << "Executing SSTW instruction..." << std::endl;
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                std::cout << "Calculating address for SSTW with immediate offset..." << std::endl;
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), W);
            } else {
                //AR[OR]
                std::cout << "Calculating address for SSTW with register offset..." << std::endl;
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), W);
            }
            std::cout << "Calculated address for SSTW: " << std::hex << temp_addr << std::dec << std::endl;
            this->do_SSTW(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SSTB:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), B);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), B);
            }
            this->do_SSTB(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SSTDB:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), DB);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), DB);
            }
            this->do_SSTDB(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        case SSTDW:
            if (sldst_instr->get_ldst_mode() <= 5) { 
                //AR[ucst10]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<immediate_operand*>(sldst_instr->get_operands(1))->get_imme_value(),
                                                            sldst_instr->get_ldst_mode(), DW);
            } else {
                //AR[OR]
                temp_addr = calculate_mem_addr(static_cast<register_operand*>(sldst_instr->get_operands(0))->get_reg_id(),
                                                        static_cast<register_operand*>(sldst_instr->get_operands(1))->get_reg_id(),
                                                            sldst_instr->get_ldst_mode(), DW);
            }
            this->do_SSTDW(temp_addr, static_cast<register_operand*>(sldst_instr->get_operands(2))->get_reg_id());
            break;
        default:
            std::cout << "ERROR: UNKNOWN SLDST OPCODE!" << std::endl;
            break;
    }
}

inline uint64_t SLDST::read_Reg(int reg_id){
    return this->RF->get_register_value(reg_id);
}
addr_size_t SLDST::calculate_mem_addr(int AR_reg_id, int OR_reg_id, int8_t op, int size){
    uint64_t AR_value = read_Reg(AR_reg_id);
    uint64_t OR_value = read_Reg(OR_reg_id);
    //负责后6个op，即偏移由OR寄存器提供
    switch (op) {
        case AR_ADD_OR_CONSTANT : 
            if (size == HW) {
                //这里直接将字节向半字对齐
                AR_value = AR_value / 4;//c++的整数除法自动向下取整
                //加上偏移
                AR_value += OR_value;
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value += OR_value;
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value += OR_value;
                return AR_value * 16;
            } else if (size == B) {
                AR_value += OR_value;
                return AR_value;
            } else if (size == DB) {
                AR_value = AR_value;
                AR_value += (OR_value * 2);
                return AR_value * 2;
            }else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_SUB_OR_CONSTANT : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value -= OR_value;
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value -= OR_value;
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value -= OR_value;
                return AR_value * 16;
            } else if (size == B) {
                AR_value -= OR_value;
                return AR_value;
            } else if (size == DB) {
                AR_value = AR_value;
                AR_value -= (OR_value * 2);
                return AR_value;
            }else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_ADD_OR_VAR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value += OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 4, 1);
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value += OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 8, 1);
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value += OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 16, 1);
                return AR_value * 16;
            }else if (size == B) {
                AR_value = AR_value;
                AR_value += OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value, 1);
                return AR_value;
            } else if (size == DB) {
                AR_value = AR_value;
                AR_value += (OR_value * 2);
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value, 1);
                return AR_value;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_SUB_OR_VAR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //加上偏移
                AR_value -= OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 4, 1);
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                AR_value = AR_value / 8;
                AR_value -= OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 8, 1);
                return AR_value * 8;
            } else if (size == DW) {
                AR_value = AR_value / 16;
                AR_value -= OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value * 16, 1);
                return AR_value * 16;
            }else if (size == B) {
                AR_value = AR_value;
                AR_value -= OR_value;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value, 1);
                return AR_value;
            } else if (size == DB) {
                AR_value = AR_value;
                AR_value -= (OR_value * 2);
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value, 1);
                return AR_value;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_VAR_ADD_OR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, (AR_value + OR_value)* 4, 1);
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value + OR_value * 8, 1);
                return AR_value;
            } else if (size == DW) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value + OR_value * 16, 1);
                return AR_value;
            } else if (size == B) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value + OR_value, 1);
                return AR_value;
            } else if (size == DB) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value + (OR_value * 2), 1);
                return AR_value;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
        case AR_VAR_SUB_OR : 
            if (size == HW) {
                //将AR寄存器的字节地址转换为半字地址
                AR_value = AR_value / 4;
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, (AR_value - OR_value)* 4, 1);
                //按字节返回访存地址
                return AR_value * 4;
            } else if (size == W) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value - OR_value * 8, 1);
                return AR_value;
            } else if (size == DW) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value - OR_value * 16, 1);
                return AR_value;
            } else if (size == B) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value - OR_value, 1);
                return AR_value;
            } else if (size == DB) {
                //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
                this->WCM->post_write_req(AR_reg_id, AR_value - OR_value * 2, 1);
                return AR_value;
            } else {
                std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
            }
            break;
    }
}
addr_size_t SLDST::calculate_mem_addr(int AR_reg_id, uint64_t imm, int8_t op, int size){
//AR寄存器存的是字节，AM的访问粒度为字。需要首先对AR寄存器+偏移后的地址按字对齐，再按粒度访问
uint64_t AR_value; 
std::cout << "Calculating memory address with AR_reg_id: " << AR_reg_id << ", imm: " << imm << ", op: " << op << ", size: " << size << std::endl;
AR_value = read_Reg(AR_reg_id);
std::cout << "AR register value (uint64_t): " << AR_value << std::endl;
//负责前6个op，即偏移由ucst10提供
switch (op) {
    case AR_ADD_CONSTANT : 
        std::cout << "AR_ADD_CONSTANT case" << std::endl;
        if (size == HW) {
            //将AR寄存器的字节地址转换为半字地址
            AR_value = AR_value / 4;
            //加上偏移
            AR_value += imm;
            //按字节返回访存地址
            std::cout << "Calculated address (HW): " << AR_value * 4 << std::endl;
            return AR_value * 4;
        } else if (size == W) {
            AR_value = AR_value / 8;
            AR_value += imm;
            return AR_value * 8;
        } else if (size == DW) {
            AR_value = AR_value / 16;
            AR_value += imm;
            std::cout << "Calculated address (DW): " << AR_value * 16 << std::endl;
            return AR_value * 16;
        }else if (size == B) {
            AR_value = AR_value;
            AR_value += imm;
            return AR_value;
        } else if (size == DB) {
            AR_value = AR_value;
            AR_value += (imm * 2);
            return AR_value;
        } else {
            std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
        }
        break;
    case AR_SUB_CONSTANT : 
        if (size == HW) {
            //将AR寄存器的字节地址转换为半字地址
            AR_value = AR_value / 4;
            //加上偏移
            AR_value -= imm;
            //按字节返回访存地址
            return AR_value * 4;
        } else if (size == W) {
            AR_value = AR_value / 8;
            AR_value -= imm;
            return AR_value * 8;
        } else if (size == DW) {
            AR_value = AR_value / 16;
            AR_value -= imm;
            return AR_value * 16;
        } else if (size == B) {
            AR_value = AR_value;
            AR_value -= imm;
            return AR_value;
        } else if (size == DB) {
            AR_value = AR_value;
            AR_value -= (imm * 2);
            return AR_value;
        } else {
            std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
        }
        break;
    case AR_ADD_VAR : 
        if (size == HW) {
            //将AR寄存器的字节地址转换为半字地址
            AR_value = AR_value / 4;
            //加上偏移
            AR_value += imm;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value * 4, 1);
            //按字节返回访存地址
            return AR_value * 4;
        } else if (size == W) {
            AR_value = AR_value / 8;
            AR_value += imm;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value * 8, 1);
            return AR_value * 8;
        } else if (size == DW) {
            AR_value = AR_value / 16;
            AR_value += imm;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value * 16, 1);
            return AR_value * 16;
        }else if (size == B) {
            AR_value = AR_value;
            AR_value += imm;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value * 8, 1);
            return AR_value;
        } else if (size == DB) {
            AR_value = AR_value;
            AR_value += (imm * 2);
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value * 16, 1);
            return AR_value;
        } else {
            std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
        }
        break;
    case AR_SUB_VAR : 
        if (size == HW) {
            //将AR寄存器的字节地址转换为半字地址
            AR_value = AR_value / 4;
            //加上偏移
            AR_value -= imm;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value * 4, 1);
            //按字节返回访存地址
            return AR_value * 4;
        } else if (size == W) {
            AR_value = AR_value / 8;
            AR_value -= imm;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value * 8, 1);
            return AR_value * 8;
        } else if (size == DW) {
            AR_value = AR_value / 16;
            AR_value -= imm;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value * 16, 1);
            return AR_value * 16;
        }else if (size == B) {
            AR_value = AR_value;
            AR_value -= imm;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value, 1);
            return AR_value * 8;
        } else if (size == DB) {
            AR_value = AR_value / 16;
            AR_value -= imm;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value, 1);
            return AR_value;
        } else {
            std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
        }
        break;
    case AR_VAR_ADD : 
        if (size == HW) {
            //将AR寄存器的字节地址转换为半字地址
            AR_value = AR_value / 4;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, (AR_value + imm)* 4, 1);
            //按字节返回访存地址
            return AR_value * 4;
        } else if (size == W) {
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value + imm * 8, 1);
            return AR_value;
        } else if (size == DW) {
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value + imm * 16, 1);
            return AR_value;
        }else if (size == B) {
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value + imm, 1);
            return AR_value;
        } else if (size == DB) {
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value + imm * 2, 1);
            return AR_value;
        } else {
            std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
        }
        break;
    case AR_VAR_SUB_OR : 
        if (size == HW) {
            //将AR寄存器的字节地址转换为半字地址
            AR_value = AR_value / 4;
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, (AR_value - imm)* 4, 1);
            //按字节返回访存地址
            return AR_value * 4;
        } else if (size == W) {
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value - imm * 8, 1);
            return AR_value;
        } else if (size == DW) {
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value - imm * 16, 1);
            return AR_value;
        }else if (size == B) {
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value - imm, 1);
            return AR_value;
        } else if (size == DB) {
            //需要修改AR寄存器为AR+OR，且不要进行字对齐，存入字节地址，1周期后写入
            this->WCM->post_write_req(AR_reg_id, AR_value - imm * 2, 1);
            return AR_value;
        } else {
            std::cout << "ERROR : WRONG MEM ACCESS SIZE" << std::endl;
        }
        break;
}
std::cout << "calculate_mem_addr: Finished calculating memory address." << std::endl;
}

void SLDST::do_SLDH(addr_size_t addr, int dst_reg_id) {
    //9个周期后，将从SM加载的数据写入目标寄存器,半字数据大小为4字节
    this->WCM->post_write_req(dst_reg_id, this->SM->load_4_bytes(addr), 9);
}
void SLDST::do_SLDHU(addr_size_t addr, int dst_reg_id){
    //9个周期后，将从SM加载的数据写入目标寄存器,半字数据大小为4字节
    this->WCM->post_write_req(dst_reg_id, this->SM->load_4_bytes(addr),9);
}
void SLDST::do_SSTH(addr_size_t addr, int src_reg_id){
    //4个周期后，将源寄存器的数据存入SM相应地址
    this->WCM->post_write_req(addr, this->RF->get_register_value(src_reg_id), HW, 4);
}
void SLDST::do_SLDW(addr_size_t addr, int dst_reg_id){
    //9个周期后，将从SM加载的数据写入目标寄存器,单字数据大小为8字节
    std::cout<<"SLDW at addr "<<std::hex<<addr<<" to reg "<<dst_reg_id<<std::endl;
    this->WCM->post_write_req(dst_reg_id, this->SM->load_8_bytes(addr),9);
    std::cout<<"SLDW request posted."<<std::endl;
}
void SLDST::do_SSTW(addr_size_t addr, int src_reg_id){
    //4个周期后，将源寄存器的数据存入AM相应地址
    std::cout<<"SSTW at addr "<<std::hex<<addr<<" from reg "<< std::dec <<src_reg_id<<std::endl;
    this->WCM->post_write_req(addr, this->RF->get_register_value(src_reg_id), W, 4);
}
void SLDST::do_SLDDW(addr_size_t addr, int dst_reg_id){
    //9个周期后，将从SM加载的数据写入目标寄存器,双字数据大小为16字节
    //dst_reg_id存储偶数寄存器编号
    std::cout<<"SLDDW at addr "<<std::hex<<addr<<" to reg "<<dst_reg_id<<std::endl;
    this->do_SLDW(addr, dst_reg_id);
    std::cout <<"SLDDW second part at addr "<<std::hex<<addr+8<<" to reg "<<dst_reg_id + 1<<std::endl;
    this->do_SLDW(addr+8, dst_reg_id + 1);
    std::cout <<"SLDDW request posted."<<std::endl;
}
void SLDST::do_SSTDW(addr_size_t addr, int src_reg_id){
    std::cout<<"SSTDW at addr "<<std::hex<<addr<<" from reg "<<std::dec<<src_reg_id <<std::endl;
    this->do_SSTW(addr, src_reg_id);
    this->do_SSTW(addr+8, src_reg_id + 1);
}
void SLDST::do_SLDB(addr_size_t addr, int dst_reg_id){
    this->WCM->post_write_req(dst_reg_id, this->SM->load_1_byte(addr), 9);
}
        
void SLDST::do_SLDBU(addr_size_t addr, int dst_reg_id){
    this->WCM->post_write_req(dst_reg_id, this->SM->load_1_byte(addr), 9);
}

//TODO:DOUBLE BYTE的操作手册里没有举例，但有这个指令，猜测是连续加载两个字节组成一个半字，不知是否为连续的两个字节
void SLDST::do_SLDDB(addr_size_t addr, int dst_reg_id){
    this->WCM->post_write_req(dst_reg_id, this->SM->load_2_bytes(addr), 9);
}
        
void SLDST::do_SLDDBU(addr_size_t addr, int dst_reg_id){
    this->WCM->post_write_req(dst_reg_id, this->SM->load_2_bytes(addr), 9);
}

//具体的根据访存大小进行数据截取的操作均在WCM中完成，此处无需处理      
void SLDST::do_SSTB(addr_size_t addr, int src_reg_id){
    //4个周期后，将源寄存器的数据存入SM相应地址
    uint64_t value = this->RF->get_register_value(src_reg_id);
    this->WCM->post_write_req(addr, value, B, 4);
}
        
void SLDST::do_SSTDB(addr_size_t addr, int src_reg_id){
    //4个周期后，将源寄存器的数据存入SM相应地址
    uint64_t value = this->RF->get_register_value(src_reg_id);
    this->WCM->post_write_req(addr, value, DB, 4);
}